package steampunk.entities;

import steampunk.GameVars;
import steampunk.art.DynamicSprite;
import steampunk.art.Sprite;
import steampunk.geom.RectGeom;
import steampunk.io.ImageManager;
import steampunk.sound.SoundManager;
import steampunk.utils.Mutil;

public class PlayerEntity extends Entity {
	
	private boolean gravity = true;
	private int jumpHeight = 60;
	private int maxjumps = 2;
	private volatile int jumps = maxjumps;
	
	private int opx = 0;
	private int opy = 0;
	
	private boolean flyUp = false;
	private boolean flyDown = false;
	private boolean flyLeft = false;
	private boolean flyRight = false;
	private double flySpeed = 500;
	
	private Entity standingOn = null;
	
	private DynamicSprite sprite;

	public PlayerEntity(int x, int y) {
		this.opx = x;
		this.opy = y;
		
		sprite = new DynamicSprite();
		
		Sprite stand = new Sprite(
				ImageManager.getSpriteGrid("sprite.jpg", 2, 12), new int[] {8}, 2);
		Sprite left = new Sprite(
				ImageManager.getSpriteGrid("sprite.jpg", 2, 12), new int[] {0, 1, 2, 3}, 2);
		Sprite right = new Sprite(
				ImageManager.getSpriteGrid("sprite.jpg", 2, 12), new int[] {4, 5, 6, 7}, 2);
		
		sprite.putSprite("idle", stand);
		sprite.putSprite("left", left);
		sprite.putSprite("right", right);
		sprite.setSprite("idle");
		
		sprite.setX(x);
		sprite.setY(y);
		
		geom = sprite;
		art  = sprite;
		
		setZLevel(1);
		
		setSolid(true);

		putAction("jump", new EAction() {
			public boolean act(Entity actOn, Object[] args) {
				if (jumps <= 0)
					return false;
				SoundManager.PLAYER.play("Fireball.wav");
				jumps--;
				double jp = jumpHeight;
				// You say "jump", I say "how high?"
				if (args != null && args.length > 0)
					jp = ((Number)args[0]).doubleValue();
				double requiredSpeed = Mutil.getVoFor(-jp, GameVars.getInstance().GRAVITY);
				actOn.setVelY(requiredSpeed);
				setAnimation("jump");
				return true;
			}
			public void deact(Entity actOn) {
				// nada
			}
		});

		putAction("down", new EAction() {
			public boolean act(Entity actOn, Object[] params) {
				if (actOn == null) return false;
				if (standingOn != null && standingOn instanceof LineFloor
						&& !((LineFloor)standingOn).allowsFallthrough())
					return false;
				actOn.moveBy(0, 1);
				setAnimation("down");
				return true;
			}
			public void deact(Entity actOn) {}
		});
		putAction("reset", new EAction() {
			public boolean act(Entity actOn, Object[] params) {
				if (actOn == null) return false;
				actOn.moveTo(opx, opy);
				actOn.setVelX(0);
				actOn.setVelY(0);
				return true;
			}
			public void deact(Entity actOn) {}
		});
		

		putAction("fly up", new EAction() {
			public boolean act(Entity actOn, Object[] params) {
				flyUp = true;
				gravity = false;
				return true;
			}
			public void deact(Entity actOn) {flyUp = false; gravity=true;}
		});
		putAction("fly down", new EAction() {
			public boolean act(Entity actOn, Object[] params) {
				gravity=false;
				flyDown = true;
				return true;
			}
			public void deact(Entity actOn) {flyDown = false; gravity=true;}
		});
		putAction("fly left", new EAction() {
			public boolean act(Entity actOn, Object[] params) {
				flyLeft = true;
				return true;
			}
			public void deact(Entity actOn) {flyLeft = false;}
		});
		putAction("fly right", new EAction() {
			public boolean act(Entity actOn, Object[] params) {
				flyRight = true;
				return true;
			}
			public void deact(Entity actOn) {flyRight = false;}
		});
	}
	
	@Override
	public void setAnimation(String name) {
		sprite.setSprite(name);
	}
	
	@Override
	protected void extraUpdate(double seconds) {
		if (gravity)
			geom.accelerate(0, GameVars.getInstance().GRAVITY * seconds);
		if (flyUp)
			geom.accelerate(0, -flySpeed*seconds);
		else if (flyDown)
			geom.accelerate(0, flySpeed*seconds);
		if (flyLeft)
			geom.accelerate(-flySpeed*seconds, 0);
		else if (flyRight)
			geom.accelerate(flySpeed*seconds, 0);
	}
	
	public void collisionStart() {
		standingOn = null;
	}
	
	@Override
	public boolean collideAction(Entity other) {
		// If I'm moving down relative to it
		if (getVelY() >= other.getVelY() && lastBottom() <= other.lastTop()) { 
			// For now, just stand on anything I hit.
			bottom(other.top());
			setVelY(other.getVelY()); // stop moving
			standingOn = other;
			if (lastVelY() > other.lastVelY()) {
				SoundManager.PLAYER.play("ding.wav");
			}
			jumps = maxjumps;
		}
		return false;
	}
}
